from rest_framework.permissions import BasePermission
from django_filters import rest_framework as filters
from django_filters.rest_framework import FilterSet
from django.db.models import Q
from .models import Product, Category, Review


# ==================== 自定义权限类 ====================

class IsOwnerOrReadOnly(BasePermission):
    """
    自定义权限: 只有创建者可以修改，其他人只能读取
    """
    def has_object_permission(self, request, view, obj):
        # 读取权限对任何请求都允许
        if request.method in ['GET', 'HEAD', 'OPTIONS']:
            return True

        # 写入权限只给对象的创建者
        return obj.created_by == request.user


class IsReviewerOrReadOnly(BasePermission):
    """
    自定义权限: 只有评论者可以修改自己的评论
    """
    def has_object_permission(self, request, view, obj):
        if request.method in ['GET', 'HEAD', 'OPTIONS']:
            return True
        return obj.reviewer == request.user


class IsAdminOrReadOnly(BasePermission):
    """
    自定义权限: 只有管理员可以修改，其他人只能读取
    """
    def has_permission(self, request, view):
        if request.method in ['GET', 'HEAD', 'OPTIONS']:
            return True
        return request.user.is_staff


class CanCreateProductPermission(BasePermission):
    """
    自定义权限: 检查用户是否可以创建产品
    例如：可能需要验证用户身份、等级等
    """
    def has_permission(self, request, view):
        if request.method != 'POST':
            return True

        # 示例：只有激活的用户才能创建产品
        if not request.user.is_authenticated:
            return False

        # 可以添加更复杂的逻辑，比如用户等级、权限组等
        return request.user.is_active


class ProductOwnerPermission(BasePermission):
    """
    产品所有者权限 - 更复杂的权限控制示例
    """
    def has_permission(self, request, view):
        """视图级权限检查"""
        if view.action == 'create':
            return request.user.is_authenticated and request.user.is_active
        return True

    def has_object_permission(self, request, view, obj):
        """对象级权限检查"""
        # GET, HEAD, OPTIONS 请求允许所有人
        if request.method in ['GET', 'HEAD', 'OPTIONS']:
            return True

        # DELETE 只允许管理员或创建者
        if view.action == 'destroy':
            return request.user.is_staff or obj.created_by == request.user

        # PUT, PATCH 只允许创建者
        if view.action in ['update', 'partial_update']:
            return obj.created_by == request.user

        return False


# ==================== 自定义过滤器 ====================

class ProductFilter(FilterSet):
    """
    产品自定义过滤器
    提供比简单字段过滤更复杂的过滤选项
    """
    # 价格范围过滤
    min_price = filters.NumberFilter(field_name="price", lookup_expr='gte', label='最低价格')
    max_price = filters.NumberFilter(field_name="price", lookup_expr='lte', label='最高价格')

    # 按名称模糊搜索
    name_contains = filters.CharFilter(field_name="name", lookup_expr='icontains', label='名称包含')

    # 按创建时间范围过滤
    created_after = filters.DateTimeFilter(field_name="created_at", lookup_expr='gte', label='创建时间晚于')
    created_before = filters.DateTimeFilter(field_name="created_at", lookup_expr='lte', label='创建时间早于')

    # 按库存状态过滤
    in_stock = filters.BooleanFilter(method='filter_in_stock', label='有库存')

    # 按分类名称过滤
    category_name = filters.CharFilter(field_name="category__name", lookup_expr='icontains', label='分类名称')

    # 按创建者用户名过滤
    created_by_username = filters.CharFilter(
        field_name="created_by__username",
        lookup_expr='icontains',
        label='创建者用户名'
    )

    # 多状态过滤
    status_in = filters.BaseInFilter(field_name='status', label='状态列表')

    class Meta:
        model = Product
        fields = {
            'category': ['exact'],
            'status': ['exact'],
            'price': ['exact', 'lt', 'gt'],
            'created_at': ['exact', 'year', 'year__gt', 'year__lt'],
        }

    def filter_in_stock(self, queryset, name, value):
        """自定义过滤方法：按库存状态过滤"""
        if value is True:
            return queryset.filter(stock__gt=0)
        elif value is False:
            return queryset.filter(stock=0)
        return queryset


class CategoryFilter(FilterSet):
    """分类过滤器"""
    name_contains = filters.CharFilter(field_name="name", lookup_expr='icontains')
    has_products = filters.BooleanFilter(method='filter_has_products')

    class Meta:
        model = Category
        fields = ['name_contains', 'has_products']

    def filter_has_products(self, queryset, name, value):
        """过滤有/无产品的分类"""
        if value is True:
            return queryset.filter(products__isnull=False).distinct()
        elif value is False:
            return queryset.filter(products__isnull=True)
        return queryset


class ReviewFilter(FilterSet):
    """评论过滤器"""
    min_rating = filters.NumberFilter(field_name="rating", lookup_expr='gte')
    max_rating = filters.NumberFilter(field_name="rating", lookup_expr='lte')
    product_name = filters.CharFilter(field_name="product__name", lookup_expr='icontains')
    reviewer_name = filters.CharFilter(field_name="reviewer__username", lookup_expr='icontains')
    comment_contains = filters.CharFilter(field_name="comment", lookup_expr='icontains')

    class Meta:
        model = Review
        fields = {
            'rating': ['exact'],
            'created_at': ['exact', 'year', 'year__gt', 'year__lt', 'date'],
            'product': ['exact'],
            'reviewer': ['exact'],
        }


# ==================== 高级过滤器示例 ====================

class AdvancedProductFilter(FilterSet):
    """
    高级产品过滤器 - 演示复杂的过滤逻辑
    """
    # 组合搜索：在名称和描述中搜索
    search = filters.CharFilter(method='filter_search', label='全文搜索')

    # 价格区间过滤
    price_range = filters.CharFilter(method='filter_price_range', label='价格区间')

    # 按评分范围过滤
    avg_rating_min = filters.NumberFilter(method='filter_avg_rating_min', label='最低平均评分')

    # 按标签过滤
    tags = filters.CharFilter(method='filter_tags', label='标签')

    # 复杂的库存过滤
    stock_level = filters.ChoiceFilter(
        choices=[
            ('out_of_stock', '缺货'),
            ('low_stock', '库存不足'),
            ('in_stock', '有库存'),
            ('high_stock', '库存充足'),
        ],
        method='filter_stock_level',
        label='库存水平'
    )

    class Meta:
        model = Product
        fields = []

    def filter_search(self, queryset, name, value):
        """全文搜索"""
        if value:
            return queryset.filter(
                Q(name__icontains=value) |
                Q(description__icontains=value) |
                Q(category__name__icontains=value)
            )
        return queryset

    def filter_price_range(self, queryset, name, value):
        """价格区间过滤"""
        # 格式: "min-max" 或 "min-" 或 "-max"
        if '-' in value:
            parts = value.split('-', 1)
            min_price = parts[0].strip()
            max_price = parts[1].strip()

            if min_price:
                queryset = queryset.filter(price__gte=float(min_price))
            if max_price:
                queryset = queryset.filter(price__lte=float(max_price))

        return queryset

    def filter_avg_rating_min(self, queryset, name, value):
        """按平均评分过滤"""
        from django.db.models import Avg
        if value:
            # 先计算每个产品的平均评分，然后过滤
            return queryset.annotate(
                avg_rating=Avg('reviews__rating')
            ).filter(avg_rating__gte=value)
        return queryset

    def filter_tags(self, queryset, name, value):
        """按标签过滤"""
        if value:
            # 支持多个标签，用逗号分隔
            tag_names = [tag.strip() for tag in value.split(',')]
            return queryset.filter(
                producttag__tag__name__in=tag_names
            ).distinct()
        return queryset

    def filter_stock_level(self, queryset, name, value):
        """按库存水平过滤"""
        if value == 'out_of_stock':
            return queryset.filter(stock=0)
        elif value == 'low_stock':
            return queryset.filter(stock__gt=0, stock__lte=10)
        elif value == 'in_stock':
            return queryset.filter(stock__gt=0)
        elif value == 'high_stock':
            return queryset.filter(stock__gt=50)
        return queryset


# ==================== 动态权限示例 ====================

class DynamicProductPermission(BasePermission):
    """
    动态权限示例 - 根据对象状态和用户角色动态判断权限
    """
    def has_object_permission(self, request, view, obj):
        user = request.user

        # 管理员拥有所有权限
        if user.is_staff:
            return True

        # 未认证用户只能查看已发布的产品
        if not user.is_authenticated:
            return request.method in ['GET', 'HEAD', 'OPTIONS'] and obj.status == 'active'

        # 普通用户权限
        if request.method in ['GET', 'HEAD', 'OPTIONS']:
            # 可以查看所有已发布产品和自己的产品
            return obj.status == 'active' or obj.created_by == user

        # 修改权限
        if view.action in ['update', 'partial_update']:
            # 只能修改自己的产品，且状态为草稿或下架
            return obj.created_by == user and obj.status in ['draft', 'inactive']

        # 删除权限
        if view.action == 'destroy':
            # 只能删除自己的草稿产品
            return obj.created_by == user and obj.status == 'draft'

        return False


# ==================== 缓存相关的权限和过滤器 ====================

class CachedPermissionMixin:
    """
    权限缓存混入类 - 用于优化权限检查的性能
    """
    def get_permissions(self):
        """缓存权限实例"""
        if not hasattr(self, '_cached_permissions'):
            self._cached_permissions = super().get_permissions()
        return self._cached_permissions


# ==================== 使用示例在视图中的集成 ====================
"""
# 在views.py中使用这些过滤器和权限的示例

from rest_framework import viewsets
from .permissions import IsOwnerOrReadOnly, ProductOwnerPermission
from .filters import ProductFilter, AdvancedProductFilter

class ExampleProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductDetailSerializer

    # 使用自定义权限
    permission_classes = [ProductOwnerPermission]

    # 使用自定义过滤器
    filterset_class = AdvancedProductFilter
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]

    # 搜索字段
    search_fields = ['name', 'description', 'category__name']

    # 排序字段
    ordering_fields = ['created_at', 'price', 'name', 'stock']
    ordering = ['-created_at']

    def get_queryset(self):
        # 可以根据用户权限返回不同的查询集
        queryset = super().get_queryset()

        if not self.request.user.is_staff:
            # 非管理员用户只能看到已发布的产品和自己的产品
            if self.request.user.is_authenticated:
                queryset = queryset.filter(
                    Q(status='active') | Q(created_by=self.request.user)
                )
            else:
                queryset = queryset.filter(status='active')

        return queryset
"""
